#include <windows.h>
#include <iostream>
#include <fstream>  // for file read/write
#include <sstream>	// for stringstream
#include <memory>	// for auto_ptr
#include <GL/gl.h>	// Header File For The OpenGL32 Library
#include <GL/glu.h>	// Header File For The GLu32 Library

#include "SDL.h"
#include "Matrix.h"
#include "Timer.h"

using namespace std;

const int MATRIX_SIZE = 5;
const int BOARD_MATRIX_SIZE = 8;
typedef Matrix<MATRIX_SIZE, MATRIX_SIZE> Matrix5x5;
typedef Matrix<BOARD_MATRIX_SIZE, BOARD_MATRIX_SIZE> Matrix8x8;

const int FRAMES_PER_SECOND = 1; 

const int TOTAL_TEXTURES = 2;
GLuint textureList[TOTAL_TEXTURES];	// This is a handle to our texture object
enum TextureObjects { CRATE01 = 0, CRATE02 };
string textureFilenames[TOTAL_TEXTURES] = { "sample01.bmp", "sample02.bmp" };

bool InitVideoSDL(int width, int height) {
	//Initializing the library
	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
		cout << "Unable to init SDL: " << SDL_GetError() << endl;
		exit(1);
	}

	//To use OpenGL, you need to get some information first,
	const SDL_VideoInfo *info = SDL_GetVideoInfo();
	if(!info) {
		/* This should never happen, if it does PANIC! */
		cout << "Video query failed: " << SDL_GetError() << endl;
		exit(2);
	}
	int bpp = info->vfmt->BitsPerPixel;

	// set bits for red: (5 = 5bits for red channel)
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
	// set bits for green:
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
	// set bits for blue:
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
	// colour depth:
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
	// You want it double buffered?
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true);

	//screen is no longer used, as openGL does all the drawing now!
	if (SDL_SetVideoMode(width, height, bpp, SDL_OPENGL | SDL_SWSURFACE) == 0) {
		cout << "Unable to set video mode: " << SDL_GetError() << endl;
		exit(3);
	}

	/* Set the title bar in environments that support it */
	SDL_WM_SetCaption("MazeGL by fseixas", NULL);
}

void InitVideoGL(int width, int height) {
	
	glEnable(GL_TEXTURE_2D);

	glViewport(0, 0, width, height);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);		// This Will Clear The Background Color To Black
	glClearDepth(1.0);				// Enables Clearing Of The Depth Buffer
	glDepthFunc(GL_LESS);				// The Type Of Depth Test To Do
	glEnable(GL_DEPTH_TEST);			// Enables Depth Testing
	glShadeModel(GL_SMOOTH);			// Enables Smooth Color Shading

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();				// Reset The Projection Matrix

	gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	// Teste
	//gluLookAt(0.0f, 10.0f, 20.0f, 
	//	0.0f, 0.0f, 0.0f, 
	//	0.0f, 1.0f, 0.0f);

	// Inside the Maze
	//gluLookAt(-1.5f, 1.0f, -12.0f, 
	//	1.0f, 0.0f, -12.0f, 
	//	0.0f, 1.0f, 0.0f);

		
}

SDL_Surface *LoadSDLImage(string filename) {
	//Temporary storage for the image that's loaded
    SDL_Surface* loadedImage = NULL;
    
    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

	//Load the image (24-bit)
    loadedImage = SDL_LoadBMP( filename.c_str() );

	//If nothing went wrong in loading the image
    if( loadedImage != NULL )
    {
        //Create an optimized image (converts loadedImage to the current bits of the screen)
        optimizedImage = SDL_DisplayFormat( loadedImage );
        
        //Free the old image
        SDL_FreeSurface( loadedImage );
    }

	//Return the optimized image
    return optimizedImage;
}

void LoadOGLTexture(string filename) {
	SDL_Surface *img = LoadSDLImage( filename.c_str() );
	GLint numColors;
	GLenum texture_format;

	// Check that the image's width is a power of 2
	if ( (img->w & (img->w - 1)) != 0 ) {
		cout << "warning: image.bmp's width is not a power of 2" << endl;
	}
	
	// Also check if the height is a power of 2
	if ( (img->h & (img->h - 1)) != 0 ) {
		cout << "warning: image.bmp's height is not a power of 2" << endl;
	}

    // get the number of channels in the SDL surface
    numColors = img->format->BytesPerPixel;
    if (numColors == 4)     // contains an alpha channel
    {
        if (img->format->Rmask == 0x000000ff)
            texture_format = GL_RGBA;
        else
            texture_format = GL_BGRA_EXT;
    } else if (numColors == 3)     // no alpha channel
    {
        if (img->format->Rmask == 0x000000ff)
            texture_format = GL_RGB;
        else
			texture_format = GL_BGR_EXT;
    } else {
        cout << "warning: the image is not truecolor..  this will probably break" << endl;
        // this error should not go unhandled
    }
        
	// Edit the texture object's image data using the information SDL_Surface gives us
	glTexImage2D( GL_TEXTURE_2D, 0, numColors, img->w, img->h, 0,
                      texture_format, GL_UNSIGNED_BYTE, img->pixels );

	// Free the SDL_Surface only if it was successfully created
	if ( img ) { 
		SDL_FreeSurface( img );
	}
}

void LoadTextures() {

	// Have OpenGL generate a texture object handle for us
	glGenTextures( TOTAL_TEXTURES, textureList);

	/*************************************************
	 * CRATE01
	 ************************************************/
	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, textureList[CRATE01] );
 
	// Set the texture's stretching properties
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

	LoadOGLTexture(textureFilenames[CRATE01]);

	/*************************************************
	 * CRATE02
	 ************************************************/
	// Bind the texture object
	glBindTexture( GL_TEXTURE_2D, textureList[CRATE02] );
 
	// Set the texture's stretching properties
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

	LoadOGLTexture(textureFilenames[CRATE02]);
}
void LoadScenario() {
	ifstream scenario;
	scenario.open("scenarios.txt");
	if(scenario.is_open()) {	
		scenario.close();
	}	
}

std::auto_ptr<Matrix5x5> GetMazeMatrix()
{
	std::auto_ptr<Matrix5x5> mat(new Matrix5x5);


	/**************
		11111
		10001
		10100
		00111
		11111
	***************/
	// Row #1
	mat->get(0,0) = 1;
	mat->get(0,1) = 1;
	mat->get(0,2) = 1;
	mat->get(0,3) = 1;
	mat->get(0,4) = 1;

	// Row #2
	mat->get(1,0) = 1;
	mat->get(1,1) = 0;
	mat->get(1,2) = 0;
	mat->get(1,3) = 0;
	mat->get(1,4) = 1;

	// Row #3
	mat->get(2,0) = 1;
	mat->get(2,1) = 0;
	mat->get(2,2) = 1;
	mat->get(2,3) = 0;
	mat->get(2,4) = 0;

	// Row #4
	mat->get(3,0) = 0;
	mat->get(3,1) = 0;
	mat->get(3,2) = 1;
	mat->get(3,3) = 1;
	mat->get(3,4) = 1;

	// Row #5
	mat->get(4,0) = 1;
	mat->get(4,1) = 1;
	mat->get(4,2) = 1;
	mat->get(4,3) = 1;
	mat->get(4,4) = 1;

    return mat;
}

std::auto_ptr<Matrix8x8> GetBoardMatrix()
{
	std::auto_ptr<Matrix8x8> mat(new Matrix8x8);

	/**************
		00000000
		00000000
		00000000
		00000000
		00000000
		00000000
		00000000
		00000000
	***************/

	for(int m=0; m<BOARD_MATRIX_SIZE; m++) {
		for(int n=0; n<BOARD_MATRIX_SIZE; n++) {
			mat->get(m,n) = 0;
		}
	}

	return mat;
}

void DrawEmptyPosition() {
	
	glBegin(GL_QUADS);				// start drawing the floor.

	// bottom of cube
	glColor3f(1.0f,0.5f,0.0f);			// Set The Color To Orange
	glVertex3f( 1.0f,-1.0f, 1.0f);		// Top Right Of The Quad (Bottom)
	glVertex3f(-1.0f,-1.0f, 1.0f);		// Top Left Of The Quad (Bottom)
	glVertex3f(-1.0f,-1.0f,-1.0f);		// Bottom Left Of The Quad (Bottom)
	glVertex3f( 1.0f,-1.0f,-1.0f);		// Bottom Right Of The Quad (Bottom)

	glEnd();
}

void DrawSolidPosition() {

	// draw a cube (6 quadrilaterals)
	glBegin(GL_QUADS);				// start drawing the cube.

	// top of cube
	glColor3f(0.0f,1.0f,0.0f);			// Set The Color To Blue
	glVertex3f( 1.0f, 0.5f,-1.0f);		// Top Right Of The Quad (Top)
	glVertex3f(-1.0f, 0.5f,-1.0f);		// Top Left Of The Quad (Top)
	glVertex3f(-1.0f, 0.5f, 1.0f);		// Bottom Left Of The Quad (Top)
	glVertex3f( 1.0f, 0.5f, 1.0f);		// Bottom Right Of The Quad (Top)

	// bottom of cube
	glColor3f(1.0f,0.5f,0.0f);			// Set The Color To Orange
	glVertex3f( 1.0f,-1.0f, 1.0f);		// Top Right Of The Quad (Bottom)
	glVertex3f(-1.0f,-1.0f, 1.0f);		// Top Left Of The Quad (Bottom)
	glVertex3f(-1.0f,-1.0f,-1.0f);		// Bottom Left Of The Quad (Bottom)
	glVertex3f( 1.0f,-1.0f,-1.0f);		// Bottom Right Of The Quad (Bottom)

	// front of cube
	glColor3f(1.0f,0.0f,0.0f);			// Set The Color To Red
	glVertex3f( 1.0f, 0.5f, 1.0f);		// Top Right Of The Quad (Front)
	glVertex3f(-1.0f, 0.5f, 1.0f);		// Top Left Of The Quad (Front)
	glVertex3f(-1.0f,-1.0f, 1.0f);		// Bottom Left Of The Quad (Front)
	glVertex3f( 1.0f,-1.0f, 1.0f);		// Bottom Right Of The Quad (Front)

	// back of cube.
	glColor3f(1.0f,1.0f,0.0f);			// Set The Color To Yellow
	glVertex3f( 1.0f,-1.0f,-1.0f);		// Top Right Of The Quad (Back)
	glVertex3f(-1.0f,-1.0f,-1.0f);		// Top Left Of The Quad (Back)
	glVertex3f(-1.0f, 0.5f,-1.0f);		// Bottom Left Of The Quad (Back)
	glVertex3f( 1.0f, 0.5f,-1.0f);		// Bottom Right Of The Quad (Back)

	// left of cube
	glColor3f(0.0f,0.0f,1.0f);			// Blue
	glVertex3f(-1.0f, 0.5f, 1.0f);		// Top Right Of The Quad (Left)
	glVertex3f(-1.0f, 0.5f,-1.0f);		// Top Left Of The Quad (Left)
	glVertex3f(-1.0f,-1.0f,-1.0f);		// Bottom Left Of The Quad (Left)
	glVertex3f(-1.0f,-1.0f, 1.0f);		// Bottom Right Of The Quad (Left)

	// Right of cube
	glColor3f(1.0f,0.0f,1.0f);			// Set The Color To Violet
	glVertex3f( 1.0f, 0.5f,-1.0f);	    // Top Right Of The Quad (Right)
	glVertex3f( 1.0f, 0.5f, 1.0f);		// Top Left Of The Quad (Right)
	glVertex3f( 1.0f,-1.0f, 1.0f);		// Bottom Left Of The Quad (Right)
	glVertex3f( 1.0f,-1.0f,-1.0f);		// Bottom Right Of The Quad (Right)
	
	glEnd();					// Done Drawing The Cube

}


void DrawMaze() {
	glPushMatrix();
	//glTranslatef(15.0f, -5.0f, -20.0f);
	//glRotatef(45, 1, 0, 0);
	//glRotatef(90, 0, 1, 0);

	std::auto_ptr<Matrix5x5> mat;
    mat = GetMazeMatrix();

	GLfloat x = 0.0f;
	GLfloat y = 0.0f;
	GLfloat z = -20.0f;
    for (int m=0; m<MATRIX_SIZE; m++)
    {
		x = 0.0f;
		y = 0.0f;
		z = z + 2.0f;

        for (int n=0; n<MATRIX_SIZE; n++)
        {
            int v = mat->get(m,n);

			glPushMatrix();			
			x = (n * 2.0f);			
			glTranslatef(x, y, z);

			cout << "Drawing[" << m << "," << n << "]: x=" << x << "; y=" << y << "; z=" << z << endl;

			switch(v) {
				case 0:
					DrawEmptyPosition();
					break;
				default:
					DrawSolidPosition();
					break;
			}
			glPopMatrix();
            //std::cout << v;
        }
		//cout << endl;
    }
	glPopMatrix();
}
void DrawCoordinateSpace() {
	
	glPushMatrix();

	// Y-axe
	glBegin(GL_LINES);

	glColor3f(1.0f, 0.0f, 0.0f);
	glVertex3f(0.0f, -10.0f, -40.0f);
	glVertex3f(0.0f, 10.0f, -40.0f);
	
	glEnd();

	glBegin(GL_TRIANGLES);

	glColor3f(1.0f, 0.0f, 0.0f);
	glVertex3f(-0.5f, 10.0f, -40.0f);
	glVertex3f(0.5f, 10.0f, -40.0f);
	glVertex3f(0.0f, 11.0f, -40.0f);

	glEnd();

	// X-axe
	glBegin(GL_LINES);

	glColor3f(0.0f, 1.0f, 0.0f);
	glVertex3f(-10.0f, 0.0f, -40.0f);
	glVertex3f(10.0f, 0.0f, -40.0f);
	
	glEnd();

	glBegin(GL_TRIANGLES);

	glColor3f(0.0f, 1.0f, 0.0f);
	glVertex3f(10.0f, -0.5f, -40.0f);
	glVertex3f(10.0f, 0.5f, -40.0f);
	glVertex3f(11.0f, 0.0f, -40.0f);

	glEnd();

	// Z-axe
	glBegin(GL_LINES);

	glColor3f(0.0f, 0.0f, 1.0f);
	glVertex3f(0.0f, 0.0f, -50.0f);
	glVertex3f(0.0f, 0.0f, -30.0f);
	
	glEnd();

	glBegin(GL_TRIANGLES);

	glColor3f(0.0f, 0.0f, 1.0f);
	glVertex3f(0.0f, -0.5f, -30.0f);
	glVertex3f(0.0f, 0.5f, -30.0f);
	glVertex3f(0.0f, 0.0f, -31.0f);

	glEnd();


	glPopMatrix();

}
void DrawBoardLines() {

	glPushMatrix();
	
	glTranslatef(0.0f, 0.0f, -10.0f);

	glColor3f(0.0f, 0.7f, 0.0f);

	float numBoards = 8.0;
	float end = numBoards / 2;
	float start = (-1) * end;
	// Draw rows
	for(int index=0; index <= numBoards; index++)
	{
		glBegin(GL_LINES);
		glVertex3f(start, end - index, 0.0f);
		glVertex3f(end, end - index, 0.0f);
		glEnd();

		glBegin(GL_LINES);
		glVertex3f(end - index, start, 0.0f);
		glVertex3f(end - index, end, 0.0f);
		glEnd();
	}

	glPopMatrix();

}

void DrawSquare() {
	
	// Bind the texture to which subsequent calls refer to
	glBindTexture( GL_TEXTURE_2D, textureList[CRATE01] );

	glBegin(GL_QUADS);				// start drawing the front.

	// front of cube
	//glColor3f(0.0f,0.6f,0.0f);			// Set The Color To Red

	glTexCoord2i( 1, 0 );
	glVertex3f( 1.0f, 1.0f, 0.0f);		// Top Right Of The Quad (Front)

	glTexCoord2i( 0, 0 );
	glVertex3f(-1.0f, 1.0f, 0.0f);		// Top Left Of The Quad (Front)

	glTexCoord2i( 0, 1 );	
	glVertex3f(-1.0f,-1.0f, 0.0f);		// Bottom Left Of The Quad (Front)

	glTexCoord2i( 1, 1 );
	glVertex3f( 1.0f,-1.0f, 0.0f);		// Bottom Right Of The Quad (Front)

	glEnd();
}

void DrawBoardSquares() {
	glPushMatrix();
	//glTranslatef(15.0f, -5.0f, -20.0f);
	//glRotatef(45, 1, 0, 0);
	//glRotatef(90, 0, 1, 0);

	std::auto_ptr<Matrix8x8> mat;
    mat = GetBoardMatrix();

	GLfloat start = (-1) * BOARD_MATRIX_SIZE;
	GLfloat x;
	GLfloat y;
	GLfloat z = -10.0f;
    for (int m=0; m<BOARD_MATRIX_SIZE; m++)
    {
		x = start;
		y = BOARD_MATRIX_SIZE - (m * 2.0f);

        for (int n=0; n<BOARD_MATRIX_SIZE; n++)
        {
            int v = mat->get(m,n);

			glPushMatrix();			
			x = start + (n * 2.0f);
			glTranslatef(x, y, z);

			cout << "Drawing[" << m << "," << n << "]: x=" << x << "; y=" << y << "; z=" << z << endl;

			switch(v) {
				case 0:
					DrawSquare();
					break;
				default:
					DrawSquare();
					break;
			}
			glPopMatrix();
        }
    }
	glPopMatrix();
}

void DrawSelectedPosition(int posX, int posY) {

	// Using gluUnProject
	// ref: http://nehe.gamedev.net/data/articles/article.asp?article=13

	// 1. Viewport Origin And Extent
	// We need to grab the current viewport. The information we need is the starting X and Y position of 
	// our GL viewport along with the viewport width and height. 
	// Once we get this information using glGetIntegerv(GL_VIEWPORT, viewport), viewport will hold the following information:

	// viewport[0]=x
	// viewport[1]=y
	// viewport[2]=width
	// viewport[3]=height 
	GLint viewport[4];								// Where The Viewport Values Will Be Stored
	glGetIntegerv(GL_VIEWPORT, viewport);			// Retrieves The Viewport Values (X, Y, Width, Height)

	// 2. The Modelview Matrix
	// Once we have the viewport information, we can grab the Modelview information. 
	// The Modelview Matrix determines how the vertices of OpenGL primitives are transformed to eye coordinates.
	GLdouble modelview[16];							// Where The 16 Doubles Of The Modelview Matrix Are To Be Stored
	glGetDoublev(GL_MODELVIEW_MATRIX, modelview);	// Retrieve The Modelview Matrix

	// 3. The Projection Matrix
	// After that, we need to get the Projection Matrix. 
	// The Projection Matrix transforms vertices in eye coordinates to clip coordinates.
	GLdouble projection[16];						// Where The 16 Doubles Of The Projection Matrix Are To Be Stored
	glGetDoublev(GL_PROJECTION_MATRIX, projection);	// Retrieve The Projection Matrix

	// 4. The Windows Screen Coordinates
	// After we have done all of that, we can grab the Windows screen coordinates. 
	// We are interested in the current mouse position. 
	GLfloat screenCoordX, screenCoordY, screenCoordZ;				// Holds Our X, Y and Z Coordinates

	screenCoordX = (float) posX;					// Holds The Mouse X Coordinate
	screenCoordY = (float) posY;					// Holds The Mouse Y Coordinate
		
	// Now Windows coordinates start with (0, 0) being at the top left whereas OpenGL coords start at the lower left. 
	// To convert to OpenGL coordinates we do the following: 	
	screenCoordY = (float) viewport[3] - screenCoordY;			// Subtract The Current Mouse Y Coordinate From The Screen Height.

	// You may have noticed the missing z coordinate, well here is how to get it:
	glReadPixels(screenCoordX, screenCoordY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &screenCoordZ);

	cout << "Screen coordinates (x,y,z) = (" << screenCoordX << "," << screenCoordY << "," << screenCoordZ << ")" <<  endl;
	
	// 5. Variables Where The Output OpenGL Coords Will Be Stored
	// All that is left to do is calculate our final OpenGL coordinates. 			
	GLdouble oglPosX, oglPosY, oglPosZ;				// Hold The Final Values

	gluUnProject( screenCoordX, screenCoordY, screenCoordZ, modelview, projection, viewport, &oglPosX, &oglPosY, &oglPosZ);

	cout << "OpenGL coordinates (x,y,z) = (" << oglPosX << "," << oglPosY << "," << oglPosZ << ")" <<  endl;

	/*	
	Now here is the completed C code that will return the correct OpenGL coordinates if you pass it the mouse coordinates: 	
		

CVector3 GetOGLPos(int x, int y)
{
	GLint viewport[4];
	GLdouble modelview[16];
	GLdouble projection[16];
	GLfloat winX, winY, winZ;
	GLdouble posX, posY, posZ;

	glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
	glGetDoublev( GL_PROJECTION_MATRIX, projection );
	glGetIntegerv( GL_VIEWPORT, viewport );

	winX = (float)x;
	winY = (float)viewport[3] - (float)y;
	glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

	gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

	return CVector3(posX, posY, posZ);
}

	*/

}

void DrawGLScene(int cursorPosX, int cursorPosY) {

	glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);	// Clear The Screen And The Depth Buffer

	//DrawBoardLines();
	DrawBoardSquares();
	//DrawMaze();
	//DrawCoordinateSpace();
	DrawSelectedPosition(cursorPosX, cursorPosY);

	// swap buffers to display, since we're double buffered.
	SDL_GL_SwapBuffers();
}

int main(int argc, char *argv[]) {
	
	InitVideoSDL(640, 480);
	atexit(SDL_Quit);

	InitVideoGL(640, 480);

	LoadTextures();

	// Mouse position
	int curPosX = 0;
	int curPosY = 0;
	// GrabInput
	bool grabInput = false;

	//Keep track of the current frame 
	int frameCounter = 0; 
	//Whether or not to cap the frame rate 
	bool cap = true;
	//The frame rate regulator 
	Timer fps; 
	// Frame rate counter
	Timer update;

	// Starts the frame timer to update the caption
	update.start();

	bool quit = false;
	while ( ! quit ) {

		//Start the frame timer 
		fps.start(); 

		/* This could go in a separate function */
		{ SDL_Event event;
		while ( SDL_PollEvent(&event) ) {
			
			if ( event.type == SDL_QUIT ) {
				quit = true;
			}

			// Keyboard keys
			if ( event.type == SDL_KEYDOWN ) {
				if ( event.key.keysym.sym == SDLK_ESCAPE ) { //If esc was pressed 
					quit = true;
				}
				else if ( event.key.keysym.sym == SDLK_i ) { //If i was pressed 
					if ( grabInput == true ) {
						SDL_WM_GrabInput(SDL_GRAB_OFF);
					}
					else {
						SDL_WM_GrabInput(SDL_GRAB_ON);
					}
					// Switch grabInput
					grabInput = !grabInput;
				}
				else if( event.key.keysym.sym == SDLK_RETURN ) { //If enter was pressed 
					//Switch cap 
					cap = ( !cap ); 
				} 
				else { // Any other key
					cout << "You pressed the key: " << (char) event.key.keysym.sym << endl;
				}
			}

			// Mouse motion
			if ( event.type == SDL_MOUSEMOTION ) {
				cout << "Mouse moved to: (" << event.motion.x << "," << event.motion.y << ")" << endl;

				curPosX = event.motion.x;
				curPosY = event.motion.y;
			}

			// Mouse button
			if ( event.type == SDL_MOUSEBUTTONDOWN ) {
				if ( event.button.button == SDL_BUTTON_LEFT )
				{
					cout << "You clicked the LEFT mouse button at: (" << event.button.x << "," << event.button.y << ")" << endl;
				}
				else if ( event.button.button == SDL_BUTTON_RIGHT )
				{
					cout << "You clicked the RIGHT mouse button at: (" << event.button.x << "," << event.button.y << ")" << endl;
				}
				else if ( event.button.button == SDL_BUTTON_MIDDLE )
				{
					cout << "You clicked the MIDDLE mouse button at: (" << event.button.x << "," << event.button.y << ")" << endl;
				}

				curPosX = event.button.x;
				curPosY = event.button.y;
			}
		}
		}

		DrawGLScene(curPosX, curPosY);

		//Increment the frame counter 
		frameCounter++;

    	//If we want to cap the frame rate 
		if( ( cap == true ) && ( fps.get_ticks() < 1000 / FRAMES_PER_SECOND ) ) { 
			//Sleep the remaining frame time 
			SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() ); 
		} 

		//If a second has passed since the caption was last updated
        if( update.get_ticks() > 1000 )
        {
            //The frame rate as a string
            std::stringstream caption;
            
            //Calculate the frames per second and create the string
            caption << "Avg. FPS: (frameCounter," << frameCounter << ") / (fps.get_ticks() / 1000," << fps.get_ticks() / 1000.f << ") = " << frameCounter / ( fps.get_ticks() / 1000.f );
            
            //Reset the caption
            SDL_WM_SetCaption( caption.str().c_str(), NULL );
            
            //Restart the update timer
            update.start();    

			frameCounter = 0;
        }
	}
	SDL_Quit();
	return 1;
}
